package com.example.demo.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.example.demo.DTO.OrderItemDTO;
import com.example.demo.DTO.OrderItemDetailDTO;
import com.example.demo.mapper.*;
import com.example.demo.pojo.*;
import com.example.demo.request.CreateOrderRequest;
import com.example.demo.service.ICartService;
import com.example.demo.service.IOrderService;
import com.example.demo.utils.OrderCodeFactory;
import com.example.demo.utils.QRCodeGenerator;
import com.google.zxing.WriterException;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements IOrderService {
	@Autowired
	OrderMapper orderMapper;
	@Autowired
	ICartService cartService;
	@Autowired
	PetsMapper petsMapper;
	@Autowired
	CartMapper cartMapper;
	@Autowired
	SellerMapper sellerMapper;
	@Autowired
	OrderItemMapper orderItemMapper;


	/**
	 * 创建订单
	 * @param createOrderReq
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public String create(CreateOrderRequest createOrderReq) {
		//首先，拿到用户ID；
		Integer userId = createOrderReq.getUserID();
		//从购物车中，查询当前用户的、购物车中的、已经被勾选的商品；
		List<Cart> cartList = cartService.list(userId);

		//遍历查到的购物车数据，从中筛选出被勾选的；
		ArrayList<Cart> cartVOArrayListTemp = new ArrayList<>();
		for (int i = 0; i < cartList.size(); i++) {
			Cart cart =  cartList.get(i);
			if (cart.getSelected()==true) {
				cartVOArrayListTemp.add(cart);
			}
		}
		cartList = cartVOArrayListTemp;
		//如果，购物车中没有已经被勾选的商品：就抛出"购物车勾选的商品为空"异常；
		if (CollectionUtils.isEmpty(cartList)) {
			Result.error("购物车勾选的商品为空");
		}

		//判断商品是否存在；如果存在，是否是上架状态；商品库存是否足够；
		validSaleStatusAndStock(cartList);

		//把【查询购物车表cart表，获得的商品数据】转化为【能够存储到order_item表的、商品数据】
		List<OrderItem> orderItemList = cartVOListToOrderItemList(cartList);

		//扣库存;(PS:前面有判断库存的逻辑，程序如果能走到这一步，就说明库存是够的)
		for (int i = 0; i < orderItemList.size(); i++) {
			OrderItem orderItem =  orderItemList.get(i);
			//首先，先拿到原先的product
			 Pets product= petsMapper.findByGoodsID(orderItem.getGoodsID());
			//然后，计算新的库存；
			int stock = product.getGoodsSum() - orderItem.getNum();
			if (stock < 0) {//上面已经检查过库存了，这儿又判断，是否是重复工作
				Result.error("重复工作");
			}

			product.setGoodsSum(product.getGoodsSum() - orderItem.getNum());
			//然后，去更新库存；也就是扣库存啦；
			petsMapper.updateByID(product);

		}
		//把【当前用户的、购物车中已经被勾选的、将要被我们下单的，商品】给删除；也就是，删除cart表中，对应的记录；
		cleanCart(cartList);

		//编写逻辑，生成一个订单号
		String orderNum = OrderCodeFactory.getOrderCode(Long.valueOf(userId));
		//创建一个订单；
		Order order = new Order();
		order.setOrderNum(orderNum);//设置订单号
		order.setUserID(userId);//设置用户id
		order.setTotalPrice(totalPrice(orderItemList));//设置订单总价
		order.setReceiverName(createOrderReq.getReceiverName());//设置收件人姓名
		order.setReceiverAddress(createOrderReq.getReceiverAddress());//设置收件人地址
		order.setReceiverPhone(createOrderReq.getReceiverPhone());//设置收件人电话
		order.setOrderStatus("unpaid");//设置订单状态
		order.setCreateTime(LocalDate.now());
		//把这个订单，添加到order表中，新增一个订单记录；
		orderMapper.insert(order);

		//也要利用循环，把订单中的每种商品，写到order_item表中；
		for (int i = 0; i < orderItemList.size(); i++) {
			OrderItem orderItem =  orderItemList.get(i);
			Pets product= petsMapper.findByGoodsID(orderItem.getGoodsID());
			orderItem.setGoodsName(product.getGoodsName());
			orderItem.setSellerID(product.getSellerID());
			orderItem.setOrderNum(orderNum);//给其赋上订单号
			orderItem.setCreateTime(LocalDate.now());
			orderItemMapper.insert(orderItem);
		}

		//返回结果；
		return orderNum;
	}


	/**
	 * 工具方法：判断列表中的商品是否存在、是否是上架状态、库存是否足够；
	 * 规则：购物车中的、已经被勾选的商品；但凡有一种不符合要求，都不行；
	 * @param cartVOArrayList
	 */
	private void validSaleStatusAndStock(List<Cart> cartVOArrayList) {
		//循环遍历、判断：【购物车中的、已经被勾选的、每一种商品】
		for (int i = 0; i < cartVOArrayList.size(); i++) {
			Cart cart =  cartVOArrayList.get(i);
			//根据【从购物车中，查到的商品信息】，去查product表；
			Pets product = petsMapper.findByGoodsID(cart.getGoodsID());
			//如果没查到（说明，商品不存在），或者，商品不是上架状态：就抛出"商品状态不可售"异常；
			if (product == null || product.getGoodsSum() < 0) {
				throw new RuntimeException("商品不存在或库存不足");
			}
			if (cart.getNum() > product.getGoodsSum()) {
				throw new RuntimeException("库存不足");
			}
		}
	}

	/**
	 * 工具方法：把【从cart购物车表中，查到的CartVO】转化为【可以存储到order_item表的，OrderItem】；
	 * @param cartVOList
	 * @return
	 */
	private List<OrderItem> cartVOListToOrderItemList(List<Cart> cartVOList) {
		List<OrderItem> orderItemList = new ArrayList<>();
		for (int i = 0; i < cartVOList.size(); i++) {
			Cart cartVO = cartVOList.get(i);
			OrderItem orderItem = new OrderItem();
			orderItem.setGoodsID(cartVO.getGoodsID());
			//下面的，其实是【商品当前的快照信息】
			orderItem.setGoodsName(cartVO.getGoodsName());//商品(当前的)名称
//			orderItem.setGoodsImg(cartVO.getGoodsImg());//商品(当前的)图片
			orderItem.setPrice(cartVO.getPrice());//商品(当前的)单价

			orderItem.setNum(cartVO.getNum());//该种商品的购买数量
			orderItem.setTotalPrice(cartVO.getNum()*cartVO.getPrice());//该种商品的总价

			orderItemList.add(orderItem);
		}
		return orderItemList;
	}

	/**
	 * 工具方法：把【当前用户的、购物车中已经被勾选的、将要被我们下单的，商品】给删除；也就是，删除cart表中，对应的记录；
	 * @param cartVOList
	 */
	private void cleanCart(List<Cart> cartVOList) {
		for (int i = 0; i < cartVOList.size(); i++) {
			Cart cartVO =  cartVOList.get(i);
			cartMapper.deleteById(cartVO.getId());
		}
	}

	/**
	 * 工具方法：获取当前订单的总价；也就是该订单中，所用种类商品的总价；
	 * @param orderItemList
	 * @return
	 */
	private double totalPrice(List<OrderItem> orderItemList) {
		double totalPrice = 0;
		for (int i = 0; i < orderItemList.size(); i++) {
			OrderItem orderItem =  orderItemList.get(i);
			totalPrice += orderItem.getTotalPrice();
		}
		return totalPrice;
	}
	/**
	 * 根据，orderNum，取消订单
	 * @param orderNum
	 */
	@Override
	public void cancel(String orderNum) {
		//首先，根据传过来的订单号，去查订单；
		Order order = orderMapper.findByOrderNo(orderNum);
		//如果没有查到订单，就抛出“订单不存在”异常；
		if (order == null) {
			throw new RuntimeException("订单不存在");
		}
		//如果订单查到了，但发现该订单不隶属当前的登录用户，就抛出“订单不属于你”异常；
		Integer userId = 1;
		if (!order.getUserID().equals(userId)) {
			throw new RuntimeException("订单不属于你");
		}

		//这个项目，在这儿，我们做了简化处理：只有订单是未付款时，才能够取消；
		// （其实，在实际中，即使付过款了，也还是能取消的，那就涉及到了退货等业务了）
		if (order.getOrderStatus().equals("unpaid")) {
			//将订单的状态，设为取消；
			order.setOrderStatus("cancel");
			//既然，订单已经被取消，也表示这个订单已经完结了；所以，这儿我们设置下订单的完结时间；
			order.setEndTime(LocalDate.now());

			//然后，更新订单信息；
			orderMapper.updateByPrimaryKeySelective(order);
		} else {
			//否则，即抛出"当前订单状态，不允许取消"异常；
			throw new RuntimeException("当前订单状态错误");
		}
	}

	/**
	 * 根据订单号，生成对应的支付二维码
	 * @param orderNum
	 * @return
	 */
	@Override
	public String qrcode(String orderNum) {
		//首先，因为这儿是非Controller，所以，通过RequestContextHolder获取HttpServletRequest；
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		//然后，拼凑订单支付url的一部分：“127.0.0.1:8083”;
		String address = "127.0.0.1:8089" + ":" + request.getLocalPort();
		//然后，完整拼凑订单支付url：“http://127.0.0.1:8083//pay?orderNo=订单号”;
		//这个就是将要写到二维码中的信息；其实，也是后面的【前台：支付订单】接口的，附带了orderNo参数的完整url
		String payUrl = "http://" + address + "/pay?orderNo=" + orderNum;

		//然后，调用我们在QRCodeGenerator工具类中编写的，生成二维码的方法；
		try {
			QRCodeGenerator.generateQRCode(payUrl, 350, 350, "C:\\Users\\86135\\Desktop\\QRCode" + orderNum + ".png");
		} catch (WriterException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		//获取二维码图片的访问地址；（PS：仅仅是访问地址，而是访问地址）
		String pngAddress = "http://" + address + "/images/" + orderNum + ".png";
		//然后，把这个二维码图片的访问地址返回；
		return pngAddress;
	}

	/**
	 * 支付订单
	 * @param orderNum
	 */
	@Override
	public void pay(String orderNum) {
		//先根据传入的orderNo，去尝试查询order
		Order order = orderMapper.findByOrderNo(orderNum);
		//如果没有找到对应的订单，就抛出“订单不存在异常”
		if (order == null) {
			throw new RuntimeException("订单不存在");
		}
		//如果订单存在，就进行接下来的操作；
		//如果，订单状态还是未付款状态;那么我们就把其设为已付款状态；（其实，这一步就是付款操作）；
		//在实际开发中，这儿其实要调用支付宝或者微信等支付接口的；之后调用微信等支付接口成功后，才能够去修改订单的order_status字段；
		if (order.getOrderStatus().equals("unpaid")) {
			order.setOrderStatus("pending");//更改订单状态为已支付；
			order.setPayTime(LocalDate.now());//设置一下支付时间；
			orderMapper.updateByPrimaryKeySelective(order);
		} else {
			//如果，当前订单状态不是未付款，就抛出“当前订单状态错误”异常；
			throw new RuntimeException("当前订单状态错误");
		}
	}
    @Override
	public void confirmOrder(String orderNum)
	{
		//先根据传入的orderNo，去尝试查询order
		Order order = orderMapper.findByOrderNo(orderNum);
		//如果没有找到对应的订单，就抛出“订单不存在异常”
		if (order == null) {
			throw new RuntimeException("订单不存在");
		}
		//如果订单存在，就进行接下来的操作；
		//如果，订单状态还是未付款状态;那么我们就把其设为已付款状态；（其实，这一步就是付款操作）；
		//在实际开发中，这儿其实要调用支付宝或者微信等支付接口的；之后调用微信等支付接口成功后，才能够去修改订单的order_status字段；
		if (order.getOrderStatus().equals("received")) {
			order.setOrderStatus("appraise");//更改订单状态为已收货
			orderMapper.updateByPrimaryKeySelective(order);
		} else {
			//如果，当前订单状态不是未付款，就抛出“当前订单状态错误”异常；
			throw new RuntimeException("当前订单状态错误");
		}

	}
	public List<OrderItemDTO> getOrderItemsGroupedBySeller(Integer userId) {
		List<Order> orders = orderMapper.selectOrderNumsAndStatusByUserId(userId);
		Map<String, String> orderStatusMap = orders.stream()
				.collect(Collectors.toMap(Order::getOrderNum, Order::getOrderStatus));

		List<String> orderNums = orderMapper.selectOrderNumsByUserId(userId);
		List<OrderItem> orderItems = orderItemMapper.selectOrderItemsByOrderNums(orderNums);
		Map<String, OrderItemDTO> orderItemMap = new HashMap<>();

		for (OrderItem item : orderItems) {
			String key = item.getOrderNum() + "_" + item.getSellerID();
			OrderItemDTO dto = orderItemMap.get(key);
			if (dto == null) {
				dto = new OrderItemDTO();
				dto.setOrderNum(item.getOrderNum());
				dto.setSellerID(item.getSellerID());
				dto.setOrderStatus(orderStatusMap.getOrDefault(item.getOrderNum(), "未知状态")); // 设置订单状态
				Seller seller = sellerMapper.selectByID(item.getSellerID());
				dto.setSellerName(seller != null ? seller.getSellerName() : "未知商家");
				dto.setItems(new ArrayList<>());
				orderItemMap.put(key, dto);
			}

			OrderItemDetailDTO detail = new OrderItemDetailDTO();
			detail.setGoodsID(item.getGoodsID());
			detail.setGoodsName(item.getGoodsName());
			detail.setPrice(item.getPrice());
			detail.setNum(item.getNum());
			dto.getItems().add(detail);
		}
		return new ArrayList<>(orderItemMap.values());
	}

	@Override
	public void refund(String orderNo) {

	}
}

